package com.atguigu.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.atguigu.common.constant.ProductConstant;
import com.atguigu.common.es.SkuEsModel;
import com.atguigu.common.to.SkuHasStockVo;
import com.atguigu.common.to.SkuReductionTo;
import com.atguigu.common.utils.R;
import com.atguigu.gulimall.product.entity.*;
import com.atguigu.gulimall.product.feign.CouponFeignService;
import com.atguigu.gulimall.product.feign.SearchFeignService;
import com.atguigu.gulimall.product.feign.WareFeignService;
import com.atguigu.gulimall.product.service.*;
import com.atguigu.gulimall.product.vo.*;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.common.utils.PageUtils;
import com.atguigu.common.utils.Query;

import com.atguigu.gulimall.product.dao.SpuInfoDao;


@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

	@Autowired
	private SpuInfoDescService spuInfoDescService;

	@Autowired
	private SkuImagesService imagesService;

	@Autowired
	private AttrService attrService;

	@Autowired
	SkuInfoService skuInfoService;

	@Autowired
	private ProductAttrValueService productAttrValueService;

	@Autowired
	SkuSaleAttrValueService skuSaleAttrValueService;

	@Autowired
	CouponFeignService couponFeignService;

	@Autowired
	BrandService brandService;

	@Autowired
	CategoryService categoryService;

	@Autowired
	WareFeignService wareFeignService;
	@Autowired
	SearchFeignService searchFeignService;

	@Override
	public PageUtils queryPageByCondition(Map<String, Object> params) {
		QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();
		String key = (String) params.get("key");


		if (!StringUtils.isEmpty(key)) {
			wrapper.and(wp -> {
				wp.eq("id", key).or().like("spu_name", key);
			});
		}

		String publishStatus = (String) params.get("status");
		if (!StringUtils.isEmpty(publishStatus)) {
			wrapper.eq("publish_status", publishStatus);
		}

		String brandId = (String) params.get("brandId");
		if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
			wrapper.eq("brand_id", brandId);
		}
		String catelogId = (String) params.get("catelogId");
		if (!StringUtils.isEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {
			wrapper.eq("catalog_id", catelogId);
		}


		IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params), wrapper);

		return new PageUtils(page);
	}

	@Override
	public void up(Long spuId) {
		//上架？1.有库存才能上架 2.保存品牌分类等信息给es，方便检索 3.修改spu的publish_status状态为上架

		//1、查出当前spuId对应的所有sku信息,品牌的名字
		List<SkuInfoEntity> skuInfoEntities = skuInfoService.getSkuInfoBySpuId(spuId);
		//TODO 4、查出当前sku的所有可以被用来检索的规格属性
		List<ProductAttrValueEntity> baseAttrs = productAttrValueService.baseAttrlistforspu(spuId);
		List<Long> attrIds = baseAttrs.stream().map(attr -> {
			return attr.getAttrId();
		}).collect(Collectors.toList());
		//通过规格参数的属性获取attr里可被检索的属性是否存在，存在就返回id，如果规格参数里面有这个id,就把规格参数转换为attrs并返回这些符合id的集合，然后设置到检索属性里面去
		List<Long> searchAttrIds = attrService.selectSearchAttrIds(attrIds); //获取可被检索的属性id集合
		HashSet<Long> idSet = new HashSet<>(searchAttrIds);  //集合去重

		//最终筛选出的检索属性
		List<SkuEsModel.Attrs> attrsList = baseAttrs.stream().filter(item -> {
			return idSet.contains(item.getAttrId());
		}).map(item -> {
			SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
			BeanUtils.copyProperties(item, attrs);
			return attrs;
		}).collect(Collectors.toList());

		//TODO 1、发送远程调用，库存系统查询是否有库存
		List<Long> skuIdList = skuInfoEntities.stream()     //查找出sku所有id
				.map(SkuInfoEntity::getSkuId)
				.collect(Collectors.toList());
		Map<Long, Boolean> stockMap = null;
		try{
			R skuHasStock = wareFeignService.getSkuHasStock(skuIdList);
			TypeReference<List<SkuHasStockVo>> typeReference = new TypeReference<List<SkuHasStockVo>>() {};
			stockMap = skuHasStock.getData(typeReference)
					.stream()
					.collect(Collectors.toMap(SkuHasStockVo::getSkuId,
					item->item.getHasStock()
					));//把查询到的是否有库存的map集合赋值，下一步设置库存信息

		}catch (Exception e){
			e.printStackTrace();
		log.error("库存服务查询异常：原因{}",e);
		}

		//2、封装每个sku的信息
		Map<Long, Boolean> finalStockMap = stockMap;
		List<SkuEsModel> collect = skuInfoEntities.stream().map(sku -> {
			SkuEsModel esModel = new SkuEsModel();
			BeanUtils.copyProperties(sku, esModel);
			esModel.setSkuPrice(sku.getPrice());
			esModel.setSkuImg(sku.getSkuDefaultImg());

			//设置库存信息
			if(finalStockMap==null){
				esModel.setHasStock(true);
			}else{
				esModel.setHasStock(finalStockMap.get(sku.getSkuId()));
			}

			//TODO 2、热度评分。0
			esModel.setHotScore(0L);
			//TODO 3、查询品牌和分类的名字信息
			BrandEntity brandEntity = brandService.getById(sku.getBrandId());
			esModel.setBrandName(brandEntity.getName());
			esModel.setBrandId(brandEntity.getBrandId());
			esModel.setBrandImg(brandEntity.getLogo());

			CategoryEntity categoryEntity = categoryService.getById(sku.getCatalogId());
			esModel.setCatalogId(categoryEntity.getCatId());
			esModel.setCatalogName(categoryEntity.getName());

			//设置检索属性
			esModel.setAttrs(attrsList);

			return esModel;
		}).collect(Collectors.toList());
		//TODO 5、将数据发给es进行保存：gulimall-search
		R r = searchFeignService.productStatusUp(collect);
		//TODO 6、修改当前spu的状态
		if(r.getCode()==0){
			//远程调用成功
			this.baseMapper.updaSpuStatus(spuId, ProductConstant.ProductStatusEnum.SPU_UP.getCode());
		}else{
			//远程调用失败
			//TODO 7、重复调用？接口幂   等性:重试机制
		}





	}

	@Override
	public PageUtils queryPage(Map<String, Object> params) {
		IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params),
				new QueryWrapper<SpuInfoEntity>());

		return new PageUtils(page);
	}

	@Override
	public void saveSpuInfo(SpuSaveVo vo) {
		/**
		 * 保存SPU基本信息
		 * 描述信息
		 * 图片集
		 * 规格参数 商品属性 积分信息
		 * 保存SPU对应的SKU信息
		 */
//        1.保存SPU基本信息
		SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
		BeanUtils.copyProperties(vo, spuInfoEntity);
		spuInfoEntity.setCreateTime(new Date());
		spuInfoEntity.setUpdateTime(new Date());
		this.saveBaseInfo(spuInfoEntity);
//        2.保存SPU描述信息
		SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
		spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
		spuInfoDescEntity.setDecript(String.join(",", vo.getDecript()));
		spuInfoDescService.saveSpuInfoDesc(spuInfoDescEntity);

//        3.保存SPU的图片集
		List<String> images = vo.getImages();
		imagesService.saveImages(spuInfoEntity.getId(), images);

//        4.保存规格参数、基本属性
		List<BaseAttrs> baseAttrs = vo.getBaseAttrs();
		List<ProductAttrValueEntity> collect = baseAttrs.stream().map(attr -> {
			ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();
			AttrEntity attrEntity = attrService.getById(attr.getAttrId());
			productAttrValueEntity.setAttrName(attrEntity.getAttrName());
			productAttrValueEntity.setAttrId(spuInfoDescEntity.getSpuId());
			productAttrValueEntity.setAttrValue(attr.getAttrValues());
			productAttrValueEntity.setQuickShow(attr.getShowDesc());
			return productAttrValueEntity;
		}).collect(Collectors.toList());
		productAttrValueService.saveProductAttr(collect);

//        5.保存SPU积分信息

//        保存SPU对应的SKU信息
		List<Skus> skus = vo.getSkus();
		if (skus != null && skus.size() > 0) {
			skus.forEach(sku -> {
				String defaultImg = "";
				for (Images image : sku.getImages()) {
					if (image.getDefaultImg() == 1) {
						defaultImg = image.getImgUrl();
					}
				}
				SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
				BeanUtils.copyProperties(sku, skuInfoEntity);
				skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
				skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
				skuInfoEntity.setSaleCount(0L);
				skuInfoEntity.setSpuId(spuInfoEntity.getId());
				skuInfoEntity.setSkuDefaultImg(defaultImg);
				//1.SKU基本信息
				skuInfoService.saveSkuInfo(skuInfoEntity);

				Long skuId = skuInfoEntity.getSkuId();

				List<SkuImagesEntity> imagesEntities = sku.getImages().stream().map(image -> {
					SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
					skuImagesEntity.setSkuId(skuId);
					skuImagesEntity.setImgUrl(image.getImgUrl());
					skuImagesEntity.setDefaultImg(image.getDefaultImg());
					return skuImagesEntity;
				}).filter(entity -> {
//					返回true就是需要，false就是删除
					return !StringUtils.isEmpty(entity.getImgUrl());
				}).collect(Collectors.toList());
				//2.SKU图片信息
				imagesService.saveBatch(imagesEntities);
				//TODO 没有图片的路径无需保存

				List<Attr> attr = sku.getAttr();
				List<SkuSaleAttrValueEntity> skuSaleAttrValueEntitys = attr.stream().map(a -> {
					SkuSaleAttrValueEntity attrValueEntity = new SkuSaleAttrValueEntity();
					BeanUtils.copyProperties(a, attrValueEntity);
					attrValueEntity.setSkuId(skuId);
					return attrValueEntity;
				}).collect(Collectors.toList());
				//3.SKU销售属性信息
				skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntitys);
				//4.SKU的优惠、满减信息  gulimall_sms
				//TODO
				SkuReductionTo skuReductionTo = new SkuReductionTo();
				BeanUtils.copyProperties(sku, skuReductionTo);
				skuReductionTo.setSkuId(skuId);
				if (skuReductionTo.getFullCount() > 0 || skuReductionTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
					R r = couponFeignService.saveSkuReduction(skuReductionTo);
					if (r.getCode() != 0) {
						log.error("远程保存sku优惠信息失败");
					}
				}

			});
		}


	}

	private void saveBaseInfo(SpuInfoEntity spuInfoEntity) {
		this.baseMapper.insert(spuInfoEntity);
	}

}